package org.example;


import java.io.*;
import java.net.URLDecoder;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * jdk22
 * 增量打包
 */
public class TestJDK22 {

    //项目名
    static String projectName = "";
    //SVN地址
    static String SVNPath = "";
    //项目路径
    static String projectPath = "";
    //开始日期
    static String startDate = "";
    //结束日期
    static String endDate = "";
    //开始版本号
    static Integer startVersion = null;
    //结束版本号
    static Integer endVersion = null;
    //更新包路径
    static String packagePath = null;

    public static void main(String[] args)  {
        doPack();
        System.out.println("执行完毕");
    }

    /**
     * 打包
     * @return 0 在日期范围或版本号范围内没有提交到SVN的文件 1 打包成功 2 打包失败
     */
    public static int doPack() {
        try {
            //更新包路径 打包放到桌面上
            packagePath = getUpdatePackageUrl(projectName);
            //打包
            return pack(executeCommands(makeCommands(startDate,endDate,startVersion,endVersion)));
        } catch (IOException | ParseException e) {
            e.printStackTrace();
            System.out.println("打包失败");
            return 2;
        }
    }

    /**
     * 生成更新包路径
     * @param projectName 项目名
     * @return 更新包路径
     */
    public static String getUpdatePackageUrl(String projectName){
        return FileSystemView.getFileSystemView().getHomeDirectory().getPath() + "\\" + projectName+String.format("%tF",new Date()).replaceAll("-","")+"更新包";
    }

    /**
     * 拼接命令
     * 规则：如果起始版本号不为空，则忽略日期条件，结束日期或结束版本号如果为空，则只查询同一日期或同一版本号下的更新文件目录
     * @param startDate 起始日期
     * @param endDate 结束日期
     * @param startVersion 起始版本号
     * @param endVersion 结束版本号
     * @return 查询svn更新文件目录cmd命令语句
     * @throws ParseException
     */
    public static String makeCommands(String startDate,String endDate,Integer startVersion,Integer endVersion ) throws ParseException {
        return startVersion == null ? "svn diff -r {" + startDate + "}:{" + addOneDay(endDate.isEmpty() ? startDate : endDate) + "} --summarize " + SVNPath
                : "svn diff -r " + (startVersion-1) + ":" + (endVersion==null ? startVersion : endVersion) + " --summarize " + SVNPath;
    }

    /**
     * 返回向后推一天的日期
     * @param day 日期
     * @return 后一天的日期
     */
    public static String addOneDay(String day) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.ENGLISH);
        return LocalDate.parse(day, formatter).plusDays(1).format(formatter);
    }

    /**
     * 执行命令，并返回更新文件路径集合
     * @param command 命令
     * @return 更新文件路径集合
     */
    public static List<String> executeCommands(String command) throws IOException {
        List<String> fileUrls = new ArrayList<>();
        Process process = Runtime.getRuntime().exec(command);
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))){
            String line;
            while ((line = reader.readLine()) != null) {
                fileUrls.add(line);
            }
            process.waitFor();
        } catch (IOException | InterruptedException e) {
            process.destroy();
            e.printStackTrace();
        }
        return fileUrls;
    }

    /**
     * 打包
     * @param fileUrls 更新文件路径
     * @return 1 打包成功 0 在日期范围或版本号范围内没有提交到SVN的文件
     * @throws IOException
     */
    public static int pack(List<String> fileUrls) throws IOException {
        if(fileUrls.size()<=0){
            System.out.println("在日期范围或版本号范围内没有提交到SVN的文件");
            return 0;
        }
        for (String line:fileUrls) {
            line = line.replaceAll(" ","").substring(1);
            if(line.indexOf("/src")>0){
                line = line.substring(0,line.indexOf("/src")) + "/WebRoot/WEB-INF/classes" + line.substring(line.indexOf("/com"));
                line = line.indexOf(".java")>0 ? line.replace(".java",".class") : line;
            }
            if(line.matches(".*%[0-9a-fA-F]{2}.*")){//URL转义处理
                line = URLDecoder.decode(line, "UTF-8");
            }
            Path sourcePath = Paths.get(line.replace(SVNPath,projectPath));
            Path targetPath = Paths.get(line.replace(SVNPath,packagePath));
            //保证svn提交的是文件而不是文件夹
            if(Files.isRegularFile(sourcePath)){
                Path targetDirPath = targetPath.getParent();
                List<Path> query = query(sourcePath.getParent(), sourcePath.getFileName().toString().replaceFirst("[.][^.]+$", ""));
                //防止含有内部类
                for (Path sourcePathSon:query) {
                    copy(sourcePathSon,targetDirPath);
                }
            }else{//直接创建提交的文件夹
                Files.createDirectories(targetPath);
            }
        }
        System.out.println("打包成功");
        return 1;
    }

    /**
     * 复制文件
     * @param sourcePath 文件所在路径
     * @param targetDirPath 文件复制后的所在目录
     */
    public static void copy(Path sourcePath,Path targetDirPath) throws IOException {
        Files.createDirectories(targetDirPath);
        Files.copy(sourcePath, targetDirPath.resolve(sourcePath.getFileName()), StandardCopyOption.REPLACE_EXISTING);
    }

    /**
     * 查询是否含有内部类，返回内部类的文件路径集合
     * @param path 外部类所在目录
     * @param prefix 外部类文件名
     * @return 内部类文件路径
     */
    public static List<Path> query(Path path,String prefix) throws IOException {
        List<Path> list = new ArrayList<>();
        Files.walkFileTree(path, new SimpleFileVisitor<>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                if (file.getFileName().toString().startsWith(prefix)) {
                    list.add(file);
                }
                return FileVisitResult.CONTINUE;
            }
        });
        return list;
    }
}